
local TurnInEverything = LibStub("AceAddon-3.0"):NewAddon("TurnInEverything", "AceEvent-3.0", "AceConsole-3.0")
--local L = LibStub("AceLocale-3.0"):GetLocale("TurnInEverything")

local isModifier = false
local isGossip = true

--[[ The defaults a user without a profile will get. ]]--
local defaults = {
	profile={
		enable = true,
		modifier = "SHIFT", --ALT, CTRL, SHIFT
		tournReward = "NONE", --NONE, WRIT, PURSE
		mode = "USABLE", -- GOLD, USABLE
		debug = false
	}
}

--[[ TurnInEverything Initialize ]]--
function TurnInEverything:OnInitialize()
	self.db = LibStub("AceDB-3.0"):New("TurnInEverythingDB", defaults, true)
	
	self.db.RegisterCallback(self, "OnProfileChanged", "OnProfileChanged")
	self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged")
	self.db.RegisterCallback(self, "OnProfileReset", "OnProfileReset")
	self.db.RegisterCallback(self, "OnNewProfile", "OnNewProfile")
	
	self:SetupOptions()
end

function TurnInEverything:OnEnable()
	self:RegisterEvent("GOSSIP_SHOW")
	self:RegisterEvent("QUEST_GREETING")
	self:RegisterEvent("QUEST_PROGRESS")
	self:RegisterEvent("QUEST_COMPLETE")
	self:RegisterEvent("MODIFIER_STATE_CHANGED")
	
	self:SendDebugMsg("Addon Enabled :: "..tostring(TurnInEverything.db.profile.enable))
end

--[[ Misc. Functions ]]--
function CompletedQuests()
	local i = 1
	local completedQuests = {}
	while GetQuestLogTitle(i) do
		-- Grab the quest details
		local questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID = GetQuestLogTitle(i)

		-- Record the names of completed quests
		if (not isHeader and isComplete == 1) then
			questTitle = string.gsub(questTitle, '%[%d+%a?%+?%]%s+', '')
			table.insert(completedQuests, questTitle)
			TurnInEverything:SendDebugMsg('CompletedQuests :: Found completed quest: ' .. tostring(questTitle))
		end
		
		i = i + 1
	end
	return completedQuests	
end

function IsEnabled()
	if (TurnInEverything.db.profile.enable) then
		return not isModifier
	else
		return false
	end
end

--[[ Event handlers ]]--
function TurnInEverything:GOSSIP_SHOW()
	if (IsEnabled()) then	
		-- Remember that we're in a gossip frame
		isGossip = true

		-- See what quests are complete
		local completedQuests = CompletedQuests()

		-- Check each active quest
		local activeQuests = { GetGossipActiveQuests() }
		self:SendDebugMsg('TurnInEverything:GOSSIP_SHOW :: Found this many active quest(s): ' .. tostring(activeQuests))
		local i = 1
		while(activeQuests[i]) do
			self:SendDebugMsg('TurnInEverything:GOSSIP_SHOW :: Found active quest: ' .. tostring(activeQuests[i]))
		
			-- Check each quest against our completed list
			for j,v in ipairs(completedQuests) do
				if (v == activeQuests[i]) then
					self:SendDebugMsg('TurnInEverything:GOSSIP_SHOW :: Matched completed quest: ' .. tostring(v))
				
					-- Select the quest and stop (i.e. process at most one completed quest per click)
					SelectGossipActiveQuest(((i - 1) / 5) + 1)
					return
				end
			end

			-- Data from GetGossipActiveQuests()
			-- http://www.wowpedia.org/API_GetGossipActiveQuests
			i = i + 5
		end
	end
end

function TurnInEverything:QUEST_GREETING()
	-- Only if enabled
	if (IsEnabled()) then
		-- Remember that we're in a quest greeting frame
		isGossip = false

		-- If there are any active quests
		numQuests = GetNumActiveQuests()
		if (numQuests ~= nil) then
			local completedQuests = CompletedQuests()

			-- Check each active quest
			for i = 1, numQuests do
				local title = GetActiveTitle(i)
				self:SendDebugMsg('TurnInEverything:QUEST_GREETING: Found active quest:' .. tostring(title))
	
				-- Check each quest against our completed list
				for j,v in ipairs(completedQuests) do
					if (v == title) then
						self:SendDebugMsg('TurnInEverything:QUEST_GREETING: Matched completed quest:' .. tostring(v))
					
						-- Select the quest and stop (i.e. process at most one completed quest per click)
						SelectActiveQuest(i)
						return
					end
				end
			end
		end	
	end
end

function TurnInEverything:QUEST_PROGRESS()
	-- Only if enabled
	if (IsEnabled()) then
		-- Display the progress text
		self:SendMsg(GetTitleText() .. ' Progress: ' .. GetProgressText())

		if(IsQuestCompletable()) then
			self:SendDebugMsg('TurnInEverything:QUEST_PROGRESS :: CompleteQuest: ' .. GetProgressText())
			CompleteQuest()
		else
			self:SendDebugMsg('TurnInEverything:QUEST_PROGRESS :: DeclineQuest: ' .. GetProgressText())
			
			-- Some Outlands quests (for whatever reason) infinite loop
			-- when using DeclineQuest().
			CloseQuest()
		end
	end
end

function TurnInEverything:QUEST_COMPLETE()
	-- Only if enabled
	if(IsEnabled()) then
		-- Display the reward text
		self:SendMsg(GetTitleText() .. ' Reward: ' .. GetRewardText())
	
		-- Track our reward choice (if possible)
		local reward = 0
		local choices = GetNumQuestChoices() or 0

		-- Always accept a 0-choice or 1-choice reward
		if (choices <= 1) then
			self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Accepting only quest reward choice')
			reward = 1

		-- Always grab the selected Argent Tournament reward, if applicable
		elseif (choices == 2 and "Champion's Writ" == GetQuestItemInfo("choice", 1) and "Champion's Purse" == GetQuestItemInfo("choice", 2)) then
			self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Accepting Argent Tournmanet quest reward ' .. tostring(self.db.profile.tournReward))
			reward = self.db.profile.tournReward

		-- Various options for multi-choice rewards
		elseif (choices > 1) then
			-- Determine the highest-valued reward and the number of usable rewards
			local usable, numUsable, highestValue, maxSell = 0,0,0,0
			
			-- Loop through all choices and determine usability and sell price
			for i = 1, choices do
				-- Determine whether the item is usable
				local _, _, _, _, isUsable = GetQuestItemInfo('choice', i)
				if (isUsable) then
					usable = i
					numUsable = numUsable + 1
				end
									
				self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Choice ' .. tostring(i) .. ' is usable: ' .. (isUsable and "Yes" or "No"))

				-- Determine the vendor sell price
				local link = GetQuestItemLink('choice', i)
				local itemString = string.match(link, 'item[%-?%d:]+')
				local linkType, itemID = strsplit(':', itemString)
				itemID = tonumber(itemID) or 0
				
				local iSellPrice = 0
				if (itemID > 0) then
					_, _, _, _, _, _, _, _, _, _, iSellPrice = GetItemInfo(itemID)
					iSellPrice = tonumber(iSellPrice) or 0
				end

				self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Choice ' .. tostring(i) .. ' value: ' .. tostring(iSellPrice))

				if (iSellPrice > 0 and iSellPrice > maxSell) then
					maxSell = iSellPrice
					highestValue = i
				end
			end

			-- When in "gold" mode grab the highest-valued reward
			if (self.db.profile.mode == "GOLD" and highestValue > 0) then
				self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Gold mode, accepting highest-value item')
				reward = highestValue

			-- When none of the choices are usable grab the highest-valued reward
			elseif (self.db.profile.mode == "USABLE" or self.db.profile.mode == "USABLE_HIGHEST_VALUE") then
				if(numUsable == 0 and highestValue > 0) then
					self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: No usable choices, accepting highest-value item')
					reward = highestValue
				elseif(numUsable == 1) then
					if(highestValue > 0 and highestValue ~= usable and self.db.profile.mode == "USABLE_HIGHEST_VALUE") then
						self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Usable mode, only one usable choice, but it is not the highest-value item')
						reward = 0
						choices = numUsable + 1						
					else
						self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Usable mode, only one usable choice, accepting usable item')
						reward = usable
					end
				else
					self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Usable mode, multiple usable choices, manually reward slection required')
					reward = 0
					choices = numUsable
				end
			end
		end
	
		-- Accept the selected reward (if possible and not debugging)
		-- Be sure to handle both "reward selected" and "no choices available"
		if ((reward >= 1 and reward <= choices) or (choices == 0 and reward <= 1)) then
			if(self.db.profile.debug) then	
				self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Will not claim rewards in debug mode. Would have selected: ' .. tostring(reward))
			else
				GetQuestReward(reward)
			
				-- Close the frame to avoid race conditions when there are multiple quests
				if (isGossip) then
					CloseGossip()
				else
					CloseQuest()
				end
			end
		elseif (self.db.profile.debug) then
			self:SendDebugMsg('TurnInEverything:QUEST_COMPLETE :: Manual reward selection required: ' .. tostring(choices) .. ' choices')
		end
	end
end

function TurnInEverything:MODIFIER_STATE_CHANGED()
	local modifier = self.db.profile.modifier
		
	if((modifier == "ALT" and IsAltKeyDown())
		or (modifier == "CTRL" and IsCtrlKeyDown())
		or (modifier == "SHIFT" and IsShiftKeyDown())) then
		isModifier = true
	else
		isModifier = false
	end
end

function TurnInEverything:OnProfileChanged(event, db)
 	self.db.profile = db.profile
end

function TurnInEverything:OnProfileReset(event, db)
	for k, v in pairs(defaults) do
		db.profile[k] = v
	end
	self.db.profile = db.profile
end

function TurnInEverything:OnNewProfile(event, db)
	for k, v in pairs(defaults) do
		db.profile[k] = v
	end
end

--[[ Sends a debugging message if debug is enabled and we have a message to send ]]--
function TurnInEverything:SendDebugMsg(msg)
	if(msg ~= nil and self.db.profile.debug) then
		TurnInEverything:Print("DEBUG :: " .. msg)
	end
end

--[[ Sends a chat message to the default frame, if we have a message to send;
	will also send a debugging message if debug is enabled ]]--
function TurnInEverything:SendMsg(msg)	
	if (msg ~= nil and self.db.profile.enable) then
		DEFAULT_CHAT_FRAME:AddMessage(msg, 1, 0.98, 0.8)
	end
	
	TurnInEverything:SendDebugMsg("SendMsg :: " .. msg)
end